package com.enjoy.xbase.qk.cookie;

import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;
import android.util.Log;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class CookieStoreManger implements CookieStore {
    private static final String COOKIE_PREFS = "sp1_cookie";           //cookie使用prefs保存
    private static final String COOKIE_NAME_PREFIX = "cookie1_";         //cookie持久化的统一前缀
    private static CookieStore instance;
    private final Map<String, ConcurrentHashMap<String, SPCookie>> cookies;
    private final SharedPreferences cookiePrefs;

    private CookieStoreManger(Context context) {
        cookiePrefs = context.getSharedPreferences(COOKIE_PREFS, Context.MODE_PRIVATE);
        cookies = new HashMap<>();

        //将持久化的cookies缓存到内存中,数据结构为 Map<Url.host, Map<CookieToken, Cookie>>
        Map<String, ?> prefsMap = cookiePrefs.getAll();
        for (Map.Entry<String, ?> entry : prefsMap.entrySet()) {
            if ((entry.getValue()) != null && !entry.getKey().startsWith(COOKIE_NAME_PREFIX)) {
                //获取url对应的所有cookie的key,用","分割
                String[] cookieNames = TextUtils.split((String) entry.getValue(), ",");
                for (String name : cookieNames) {
                    Log.e("保存的cookie", name);
                    //根据对应cookie的Key,从xml中获取cookie的真实值
                    String encodedCookie = cookiePrefs.getString(COOKIE_NAME_PREFIX + name, null);
                    Log.e("保存的cookie值", encodedCookie);
                    if (encodedCookie != null) {
                        SPCookie decodedCookie = SerializableUtil.decodeObject(encodedCookie);
                        if (decodedCookie != null) {
                            if (!cookies.containsKey(entry.getKey())) {
                                cookies.put(entry.getKey(), new ConcurrentHashMap<String, SPCookie>());
                            }
                            cookies.get(entry.getKey()).put(name, decodedCookie);
                        }
                    }
                }
            }
        }
    }

    public static void init(Context context) {
        instance = new CookieStoreManger(context);
    }

    public static CookieStore getInstance() {
        return instance;
    }

    /**
     * 当前cookie是否过期
     */
    private static boolean isCookieExpired(SPCookie cookie) {
        return cookie.expiresAt < System.currentTimeMillis();
    }

    private String getCookieToken(SPCookie cookie) {
        return cookie.name + "@" + cookie.domain;
    }

    /**
     * 将url的所有Cookie保存在本地
     */
    public synchronized void saveCookie(String host, List<SPCookie> urlCookies) {
        for (SPCookie cookie : urlCookies) {
            saveCookie(host, cookie);
        }
    }

    public synchronized void saveCookie(String host, SPCookie cookie) {
        if (!cookies.containsKey(host)) {
            cookies.put(host, new ConcurrentHashMap<String, SPCookie>());
        }
        //当前cookie是否过期
        if (isCookieExpired(cookie)) {
            removeCookie(host, cookie);
        } else {
            saveCookie(host, cookie, getCookieToken(cookie));
        }
    }

    /**
     * 保存cookie，并将cookies持久化到本地
     */
    private void saveCookie(String host, SPCookie cookie, String cookieToken) {
        //内存缓存
        cookies.get(host).put(cookieToken, cookie);
        //文件缓存
        SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
        prefsWriter.putString(host, TextUtils.join(",", cookies.get(host).keySet()));
        prefsWriter.putString(COOKIE_NAME_PREFIX + cookieToken, SerializableUtil.objectToString(cookie));
        prefsWriter.apply();
    }

    /**
     * 根据当前url获取所有需要的cookie,只返回没有过期的cookie
     */
    public synchronized List<SPCookie> loadCookie(String host) {
        List<SPCookie> ret = new ArrayList<>();
        if (!cookies.containsKey(host)) return ret;
        Collection<SPCookie> urlCookies = cookies.get(host).values();
        for (SPCookie cookie : urlCookies) {
            if (isCookieExpired(cookie)) {
                removeCookie(host, cookie);
            } else {
                ret.add(cookie);
            }
        }
        return ret;
    }

    /**
     * 根据url移除当前的cookie
     */
    public synchronized boolean removeCookie(String host, SPCookie cookie) {
        if (!cookies.containsKey(host)) return false;
        String cookieToken = getCookieToken(cookie);
        if (!cookies.get(host).containsKey(cookieToken)) return false;

        //内存移除
        cookies.get(host).remove(cookieToken);
        //文件移除
        SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
        if (cookiePrefs.contains(COOKIE_NAME_PREFIX + cookieToken)) {
            prefsWriter.remove(COOKIE_NAME_PREFIX + cookieToken);
        }
        prefsWriter.putString(host, TextUtils.join(",", cookies.get(host).keySet()));
        prefsWriter.apply();
        return true;
    }

    public synchronized boolean removeCookie(String host) {
        if (!cookies.containsKey(host)) return false;

        //内存移除
        ConcurrentHashMap<String, SPCookie> urlCookie = cookies.remove(host);
        //文件移除
        Set<String> cookieTokens = urlCookie.keySet();
        SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
        for (String cookieToken : cookieTokens) {
            if (cookiePrefs.contains(COOKIE_NAME_PREFIX + cookieToken)) {
                prefsWriter.remove(COOKIE_NAME_PREFIX + cookieToken);
            }
        }
        prefsWriter.remove(host);
        prefsWriter.apply();

        return true;
    }

    public synchronized boolean removeAllCookie() {
        //内存移除
        cookies.clear();
        //文件移除
        SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
        prefsWriter.clear();
        prefsWriter.apply();
        return true;
    }

    /**
     * 获取所有的cookie
     */
    public synchronized List<SPCookie> getAllCookie() {
        List<SPCookie> ret = new ArrayList<>();
        for (String key : cookies.keySet()) {
            ret.addAll(cookies.get(key).values());
        }
        return ret;
    }

    public synchronized List<SPCookie> getCookie(String host) {
        List<SPCookie> ret = new ArrayList<>();
        Map<String, SPCookie> mapCookie = cookies.get(host);
        if (mapCookie != null) ret.addAll(mapCookie.values());
        return ret;
    }
}